//
//  CacheManager.swift
//  ImGuider X
//
//  Created by llt on 2018/9/25.
//  Copyright © 2018 imguider. All rights reserved.
//

import UIKit

class CacheManager: NSObject {
    
    /// 单例对象
    static let share = CacheManager()
    
    private let cache: NSCache<AnyObject, AnyObject>!
    
    private let fileManager  = FileManager()
    
    private let ioQueue: DispatchQueue!
    
    private let diskCachePath: String!
    
    override init() {
        
        cache = NSCache()
        
        ioQueue = DispatchQueue(label: "com.imguider.imguiderx.cache")
        
        let dstPath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first! as NSString
        
        diskCachePath = dstPath.appendingPathComponent("imguidercache")
    }
    
    
    private func cachePath(forComputedKey key: String) -> String {
        
        return (diskCachePath as NSString).appendingPathComponent(key)
    }
    
    
    func cleanAll() {
        
        cache.removeAllObjects()
    }
    
    func store(_ obj:Data,forKey key:String,toDisk:Bool = true) {
        
        cache.setObject(obj as AnyObject, forKey: key as AnyObject)
        
        if toDisk {
            
            ioQueue.async {
                
                [weak self] in
                guard let `self` = self else { return }
                
                if !self.fileManager.fileExists(atPath: self.diskCachePath) {
                    
                    try? self.fileManager.createDirectory(atPath: self.diskCachePath, withIntermediateDirectories: true, attributes: nil)
                }
                self.fileManager.createFile(atPath: self.cachePath(forComputedKey: key), contents: obj, attributes: nil)
                
            }
        }
    }
    
    func remove(forKey key:String,toDisk:Bool = true) {
        
        cache.removeObject(forKey: key as AnyObject)
        
        if toDisk {
            
            ioQueue.async {

                [weak self] in
                guard let `self` = self else { return }
                
                try? self.fileManager.removeItem(atPath: self.cachePath(forComputedKey: key))
            }
        }
    }
    
    func retrieve(forKey key:String, complete:@escaping ((Data?) -> Void)) {
        
        if let data = cache.object(forKey: key as AnyObject) as? Data {
            
            complete(data)
            return
        }
        
        ioQueue.async {
            
            guard let data = try? Data(contentsOf: URL(fileURLWithPath: self.cachePath(forComputedKey: key))) else {
                
                DispatchQueue.main.async {
                    
                    complete(nil)
                }
                
                return
            }
            
            DispatchQueue.main.async {
                
                complete(data)
            }
        }
    }
}

